#ifndef ACO_TOOL_H
#define ACO_TOOL_H

#include "define.h"
#include <QPoint>

class tool {
public:

    static QPoint start;
    static QPoint stop;
    static int count;
    static QPoint origin;

    static inline pair_int numToPair(int size, int num){
        pair_int t;
        t.second = num / size;
        t.first = num % size;

        return t;
    }

    static inline int pairToNum(int size, pair_int pai){
        int t = 0;
        t += pai.second * size;
        t += pai.first;

        return t;
    }

    static inline double distance(pair_int p1, pair_int p2) {
        return pow(pow(p1.first - p2.first, 2) + pow(p1.second - p2.second, 2), 0.5);
    }

    static inline int findMin(std::vector<double> array) {
        double min = INT32_MAX, res = 0, k = array.size();
        for(int i=0; i<k; ++i) {
            if(array[i] < min){
                min = array[i];
                res = i;
            }
        }
        return res;
    }

    static inline Direction judgeDirection(pair_int start, pair_int end) {
        if((end.first - start.first) == 1 && !(end.second - start.second)) {
            return RIGHT;
        } else if((end.first - start.first) == 1 && (end.second - start.second) == 1){
            return LOWERRIGHT;
        } else if(!(end.first - start.first) && (end.second - start.second) == 1){
            return LOWER;
        } else if((end.first - start.first) == -1 && (end.second - start.second) == 1){
            return LOWERLEFT;
        } else if((end.first - start.first) == -1 && !(end.second - start.second)){
            return LEFT;
        } else if((end.first - start.first) == -1 && (end.second - start.second) == -1){
            return UPPERLEFT;
        } else if(!(end.first - start.first) && (end.second - start.second) == -1){
            return UPPER;
        } else if((end.first - start.first) == 1 && (end.second - start.second) == -1){
            return UPPERRIGHT;
        } else {
            return OTHER;
        }
    }

    static void transposeMatrix(std::vector<std::vector<int>> &matrix) {
        int k = matrix.size();
        for(int i = 1; i < k; ++i) {
            for(int j = 0; j < i; ++j) {
                std::swap(matrix[i][j], matrix[j][i]);
            }
        }
    }


    static std::vector<QPoint> routeToPoint(std::vector<pair_int> bestPathe, pair_int sta, int scale) {
        std::vector<QPoint> qtDraw;

        int x = sta.first*scale+scale/2;
        int y = sta.second*scale+scale/2;
        int k = bestPathe.size();

        qtDraw.push_back(QPoint(x, y));
        Direction direction;
        //pair_int t;
        for(int i = 1; i < k; ++i) {

            direction = tool::judgeDirection(bestPathe[i-1], bestPathe[i]);
            //std::cout << (int)direction << std::endl;
            switch (direction) {
                case RIGHT:

    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x += 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    //qtDraw.push_back(cv::Point(x, y));

                    break;
                case LOWERRIGHT:
    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x += 1;
                        y += 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case LOWER:

    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        y += 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case LOWERLEFT:

    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x -= 1;
                        y += 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case LEFT:
    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x -= 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case UPPERLEFT:
    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x -= 1;
                        y -= 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case UPPER:

    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        y -= 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
                case UPPERRIGHT:

    //            std::cout << cv::Point(x, y) << std::endl;
    //            std::cout << cv::Point(bestPathe[i].first*SCALE+SCALE/2, bestPathe[i].second*SCALE+SCALE/2) << std::endl;
                    while (x != bestPathe[i].first*scale+scale/2 || y != bestPathe[i].second*scale+scale/2) {
                        x += 1;
                        y -= 1;
                        qtDraw.push_back(QPoint(x, y));
                        //std::cout << cv::Point(x, y) << std::endl;
                    }
                    break;
            }
        }

        return qtDraw;
    }

};


#endif //ACO_TOOL_H
